package com.lepu.app.fun.chat.core;

import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;

import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.DefaultPacketExtension;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smackx.delay.packet.DelayInformation;
import org.jivesoftware.smackx.muc.MultiUserChat;
import org.jivesoftware.smackx.receipts.DeliveryReceipt;
import org.jivesoftware.smackx.receipts.DeliveryReceiptManager;
import org.jivesoftware.smackx.receipts.DeliveryReceiptRequest;

import com.app.application.MyApplication;
import com.app.config.UserConfig;
import com.app.utils.Const;
import com.app.utils.LoginUtil;
import com.app.utils.ObserverConst;
import com.app.utils.Setting;
import com.core.lib.utils.ObserverManager;
import com.core.lib.utils.main.AppManager;
import com.core.lib.utils.main.DateUtilBase;
import com.core.lib.utils.main.LogUtilBase;
import com.core.lib.utils.main.UtilityBase;
import com.lepu.app.fun.chat.activity.ChatMainActivity;
import com.lepu.app.fun.chat.bean.ChatMessage;
import com.lepu.app.fun.chat.bean.ChatRoomMessage;
import com.lepu.app.fun.chat.bean.ChatSession;
import com.lepu.app.fun.chat.bean.Media;
import com.lepu.app.fun.chat.util.ChatConst;
import com.lepu.app.fun.chat.util.Constants;
import com.lepu.app.fun.chat.util.LectureUtil;
import com.lepu.app.main.activity.MainTabActivity;
import com.lepu.app.main.service.AppService;

import java.util.Collection;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
 * @author wxd
 */
public class ClientChatXmppImpl implements IClientChat {

    private static final String TAG = "ClientChatXmppImpl";
    private String serverAddress;
    private XMPPConnection connection;
    private boolean connectionClosed = true;
    private XmppListener xmppListener = null;

    private Timer mConnectTimer = null;
    public boolean mConneting = false;

    static class ClientChatHolder {
        static IClientChat clientChat = new ClientChatXmppImpl();
    }

    public static IClientChat getInstance() {
        return ClientChatHolder.clientChat;
    }

    private ClientChatXmppImpl() {
        ProviderManager.addExtensionProvider(DeliveryReceipt.ELEMENT,
                DeliveryReceipt.NAMESPACE, new DeliveryReceipt.Provider());
        ProviderManager.addExtensionProvider(DeliveryReceiptRequest.ELEMENT,
                new DeliveryReceiptRequest().getNamespace(),
                new DeliveryReceiptRequest.Provider());
        ProviderManager.addIQProvider("query",
                "http://kanebay.com/protocol/server#time",
                new ServerTimeIQProvider());
        ProviderManager.addIQProvider("query",
                "http://kanebay.com/protocol/offlinemessage#exist",
                new MessageStateIQProvider());
        ProviderManager.addExtensionProvider(MediaPacketExtension.ELEMENT_NAME,
                MediaPacketExtension.NAMESPACE,
                new MediaPacketExtensionProvider());
        ProviderManager.addExtensionProvider(
                ServerReceiptExtension.ELEMENT_NAME,
                ServerReceiptExtension.NAMESPACE,
                new ServerReceiptPacketExtensionProvider());
    }

    @Override
    public void disconnect() {
        try {
            if (connection == null ||  !connection.isConnected()) {
                LogUtilBase.LogD(TAG, "chat disconnect fail");
                return;
            }
            connection.disconnect(); // todo NetworkOnMainThreadException
            LogUtilBase.LogD(TAG, "chat disconnect success");
        } catch (SmackException.NotConnectedException e) {
            LogUtilBase.LogD(TAG, "chat disconnect fail");
        }
    }

    @Override
    public void login(final String host, final int port, final long userId,
                      final String password) {
        this.serverAddress = host;
        // setup providers
        AsyncTask<Void, Void, Boolean> connectionThread = new AsyncTask<Void, Void, Boolean>() {
            @Override
            protected Boolean doInBackground(Void... arg0) {
                boolean isConnected = false;

                LogUtilBase.LogD(TAG,"openfire login enter");
                if(mConneting)
                {
                    LogUtilBase.LogD(TAG,"openfire login return");
                    return isConnected;
                }
                mConneting = true;
                try {
                    ConnectionConfiguration config = new ConnectionConfiguration(
                            serverAddress, port);
                    //是否允许重新连接
                    config.setReconnectionAllowed(false);
                    // 设置成disabled，则不会去验证服务器证书是否有效，默认为enabled
                    config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
                    // SASLAuthentication.supportSASLMechanism("PLAIN",0);
                    // 设置可以调试，默认为false，老版本的写法为XMPPConnection.DEBUG_ENABLED =
                    // true;
                    config.setDebuggerEnabled(true);
                    // 设置是否在登陆的时候告诉服务器，默认为true
                    // need to set to false to retrieve offline messages
                    config.setSendPresence(true);
                    connection = new XMPPTCPConnection(config);
                    // 设置等待时间
                    // connection.setPacketReplyTimeout(5000);
                    // enable autoReceipt
                    DeliveryReceiptManager.getInstanceFor(connection)
                            .enableAutoReceipts();
                    DeliveryReceiptManager.getInstanceFor(connection)
                            .setAutoReceiptsEnabled(true);
                    // Chang 10-09 好像没有什么特别的用处， 具体回执已经在消息接听代码处理了
                    // DeliveryReceiptManager.getInstanceFor(connection).addReceiptReceivedListener(new
                    // SimpleReceiptReceivedListener());
                    connection
                            .addConnectionListener(new XMPPConnectionListener(
                                    ClientChatXmppImpl.getInstance(), host,
                                    port, userId, password));
                    connection.connect();
                    connection.login(String.valueOf(userId), password);
                    xmppListener.onLogin();

                    sendServerTimeIQ();
                    isConnected = true;
                    connectionClosed = false;
                    mConneting = false;
                    LogUtilBase.LogD(TAG, "xmpp login success");
                } catch (Exception e) {
                    LogUtilBase.LogD(TAG, "xmpp login fail");
                    mConneting = false;
                    xmppListener.onXmppError(0, null, MessageBuilder
                            .buildError(Constants.Error.XMPP_LOGIN_ERROR, e));

                    startConnectTimer();
                }
                return isConnected;
            }
        };
        connectionThread.execute();
    }

    @Override
    public void sendMessage(ChatMessage chatMessage) {

        AsyncTask<ChatMessage, Void, Void> connectionThread = new AsyncTask<ChatMessage, Void, Void>() {
            @Override
            protected Void doInBackground(ChatMessage... arg0) {
                ChatMessage chatMessage = arg0[0];

                try {
                    if (connection == null || isConnectionClosed() || !connection.isConnected()) {
                        xmppListener.onXmppError(chatMessage.getSessionId(),
                                chatMessage.getMessageId(),
                                MessageBuilder.buildError(
                                        Constants.Error.XMPP_CONNECTION_ERROR,
                                        "xmpp connection is closed"));

                        if(chatMessage != null)
                        {
                            chatMessage.setSendStatus(Constants.Chat.CHAT_SEND_STATUS_LOST);
                            ChatDAO.getInstance().replaceMessage(chatMessage);
                            ChatManager.getInstance().notifyUIDataChange(new ChatSession(),
                                    chatMessage, Constants.Chat.CHAT_MESSAGE_CHANGED);
                        }
                        return null;
                    }

                    String jid = String.valueOf(chatMessage.getToUserId());
                    Message message = new Message(jid, Message.Type.chat);
                    DeliveryReceiptManager.addDeliveryReceiptRequest(message);

                    //拼接message
                    message.setPacketID(chatMessage.getMessageId());

                    message.setFrom(MessageBuilder.getDomain(String.valueOf(chatMessage.getHostUserId())));
                    message.setTo(MessageBuilder.getDomain(String.valueOf(chatMessage.getToUserId())));

                    Media media = chatMessage.getMedia();
                    if (media == null) {
                        //for others application
                        //String content = String.format("<![CDATA[" + "%s" + "]]>", chatMessage.getContent());
                        String content = chatMessage.getContent();
                        message.setBody(content);

                        addExensionEle(chatMessage, message);
                        connection.sendPacket(message);

                        return null;
                    }

                    String info = "";
                    String chat = "";
                    if (chatMessage.getFromUserId() == Constants.Staff) {
                        //在线咨询
                        info = Constants.Chat.INFO_CONSULT;
                        chat = Constants.Chat.CHAT;
                    }else if (chatMessage.getFromUserId() == Constants.AskDoctor){
                        //私聊
                        info = Constants.Chat.INFO_ASK_DOCTOR;
                        chat = Constants.Chat.ASK_DOCTOR;
                    }else if (chatMessage.getFromUserId() == Constants.AskDoctorAddNotice){
                        //通知
                        info = Constants.Chat.INFO_UserToDoctor;
                        chat = Constants.Chat.NOTICE;
                    }

                    MediaPacket mediaPacket = MessageBuilder
                            .buildMediaPacket(media,chat,
                                    String.valueOf(chatMessage.getToUserId()),info);
                    mediaPacket.setMessage(message);
                    connection.sendPacket(mediaPacket);

                    return null;
                } catch (SmackException.NotConnectedException e) {
                    xmppListener.onXmppError(chatMessage.getSessionId(),
                            chatMessage.getMessageId(),
                            MessageBuilder.buildError(
                                    Constants.Error.XMPP_CONNECTION_ERROR, e));
                } catch (Exception e) {
                    xmppListener.onXmppError(chatMessage.getSessionId(),
                            chatMessage.getMessageId(),
                            MessageBuilder.buildError(
                                    Constants.Error.XMPP_CONNECTION_ERROR, e));
                }
                return null;
            }
        };

        connectionThread.execute(chatMessage);
    }

    @Override
    public void sendChatRoomMessage(ChatRoomMessage chatMessage) {
        AsyncTask<ChatRoomMessage, Void, Void> connectionThread = new AsyncTask<ChatRoomMessage, Void, Void>() {
            @Override
            protected Void doInBackground(ChatRoomMessage... arg0) {
                ChatRoomMessage chatRoomMessage = arg0[0];
                try {

                    if (connection == null || isConnectionClosed() || !connection.isConnected()) {
                        LogUtilBase.LogD(TAG, "Connection is null or closed. Failed to sent out message to " + chatRoomMessage.getToUserId() + ", msg = " + chatRoomMessage.getContent());
                        xmppListener.onXmppError(chatRoomMessage.getSessionId(), chatRoomMessage.getMessageId(), MessageBuilder.buildError(Constants.Error.XMPP_CONNECTION_ERROR, "xmpp connection is null or closed"));

                        if(chatRoomMessage != null)
                        {
                            chatRoomMessage.setSendStatus(Constants.Chat.CHAT_SEND_STATUS_LOST);
                            ChatManager.getInstance().notifyChatRoomUIDataChange(null,
                                    chatRoomMessage, Constants.Chat.CHAT_MESSAGE_CHANGED);
                        }

                        return null;
                    }

                    //能发都是没有关闭
                    setConnectionClosed(false);
                    //chatroom id
                    String jid = chatRoomMessage.getToUserId();
                    Message message = new Message(jid, Message.Type.chat);
                    DeliveryReceiptManager.addDeliveryReceiptRequest(message);

                    //拼接message
                    message.setPacketID(chatRoomMessage.getMessageId());

                    message.setFrom(MessageBuilder.getDomain(String.valueOf(chatRoomMessage.getHostUserId())));
                    message.setTo(MessageBuilder.getDomain(chatRoomMessage.getChatRoomID()));

                    Media media = chatRoomMessage.getMedia();
                    if (media == null) {
                        //for others application
                        //String content = String.format("<![CDATA[" + "%s" + "]]>", chatRoomMessage.getContent());
                        String content = chatRoomMessage.getContent();
                        message.setBody(content);

                        ChatRoomPacketExtension extension = new ChatRoomPacketExtension(ChatRoomPacketExtension.ELEMENT_NAME_EXTEND,
                                ChatRoomPacketExtension.NAMESPACE_EXTEND);
                        extension.setChatType(Constants.Chat.GROUPCHAT);
                        extension.setGroupID(chatRoomMessage.getChatRoomID());
                        extension.setInfo1("");

                        String atUserIDInfo = LectureUtil.getInstance().getUserIDsByContent(content);
                        extension.setInfoAtReceive(atUserIDInfo);
                        message.addExtension(extension);

                        LogUtilBase.LogD(TAG, "message===>>" + message.toString());

                        connection.sendPacket(message);

                        return null;
                    }

                    MediaPacket mediaPacket = MessageBuilder
                            .buildMediaPacket(media,Constants.Chat.GROUPCHAT,
                                    String.valueOf(chatRoomMessage.getChatRoomID()),"");
                    mediaPacket.setMessage(message);
                    connection.sendPacket(mediaPacket);

                    LogUtilBase.LogD(TAG, "send a extension message to " + chatRoomMessage.getToUserId());
                    return null;
                } catch (SmackException.NotConnectedException e) {
                    LogUtilBase.LogE(null, e.toString());
                    xmppListener.onXmppError(chatRoomMessage.getSessionId(), chatRoomMessage.getMessageId(), MessageBuilder.buildError(Constants.Error.XMPP_CONNECTION_ERROR, e));
                } catch (Exception e) {
                    LogUtilBase.LogE(null, e.toString());
                    xmppListener.onXmppError(chatRoomMessage.getSessionId(), chatRoomMessage.getMessageId(), MessageBuilder.buildError(Constants.Error.XMPP_CONNECTION_ERROR, e));
                }
                return null;
            }
        };
        connectionThread.execute(chatMessage);
    }

    /**
     * 添加例外
     *
     * @param chatMessage
     * @param message
     */
    private void addExensionEle(ChatMessage chatMessage, Message message) {
        FromTypeExtension extension = new FromTypeExtension(FromTypeExtension.ELEMENT_NAME_EXTEND,
                FromTypeExtension.NAMESPACE_EXTEND);

        String chat = "";
        if (chatMessage.getFromUserId() == Constants.Staff) {
            //在线咨询
            extension.setInfo1(Constants.Chat.INFO_CONSULT);
            chat = Constants.Chat.CHAT;
        }else if (chatMessage.getFromUserId() == Constants.AskDoctor){
            //私聊
            extension.setInfo1(Constants.Chat.INFO_ASK_DOCTOR);
            chat = Constants.Chat.ASK_DOCTOR;
        }else if (chatMessage.getFromUserId() == Constants.AskDoctorAddNotice){
            //通知
            extension.setInfo1(Constants.Chat.INFO_UserToDoctor);
            chat = Constants.Chat.NOTICE;
        }
        extension.setChatType(chat);
        message.addExtension(extension);
    }

    @Override
    public void listenIncomingMessages() {

        // PacketFilter filter = new AndFilter(new
        // PacketTypeFilter(Message.class), new PacketTypeFilter(IQ.class));

        PacketListener iqListener = new PacketListener() {
            @Override
            public void processPacket(Packet packet) {
                if (packet instanceof MessageStateIQ) {
                    MessageStateIQ iq = (MessageStateIQ) packet;
                    xmppListener.onIQMessage(iq);
                } else if (packet instanceof ServerTimeIQ) {
                    ServerTimeIQ iq = (ServerTimeIQ) packet;
                    xmppListener.onServerTime(iq.getServerTime());
                }
            }
        };

        PacketListener msgListener = new PacketListener() {
            @Override
            public void processPacket(Packet packet) {
                //Presence 类型为新添加的类型
                if(packet == null)
                {
                    return;
                }
                LogUtilBase.LogD(TAG, "listenIncomingMessages packet: " + packet.getPacketID());
                Message message = (Message) packet;
                ChatMessage chatMessage = null;
                //消息回执
                PacketExtension userblocked = message.getExtension(ServerReceiptExtension.ELEMENT_NAME,
                        ServerReceiptExtension.NAMESPACE);
                if (userblocked != null) {
                    boolean isReturn = false;
                    String type = ((ServerReceiptExtension) userblocked).getChatType();
                    String content = ((ServerReceiptExtension) userblocked).getContent();
                    String messageID = ((ServerReceiptExtension) userblocked).getMessageId();

                    if (type.equals(Constants.Chat.GROUPCHAT)) {
                        //群聊消息回执
                        if (content.contains("blocked")) {
                            isReturn = true;
                            LogUtilBase.LogD(ClientChatXmppImpl.class.getSimpleName(), "this user is blocked");

                            ServerReceiptExtension serverReceiptExtension = message.getExtension(ServerReceiptExtension.ELEMENT_NAME,
                                    ServerReceiptExtension.NAMESPACE);
                            ChatRoomMessage chatRoomMessage = MessageBuilder.buildRoomMessageFromServerReceipt(0, serverReceiptExtension, serverReceiptExtension.getMessageId());

                            LogUtilBase.LogD(TAG, "onReceiveReceiptRoom for server receipt:" + chatRoomMessage.getMessageId());
                            xmppListener.onReceiveReceiptRoom(chatRoomMessage);
                        } else if (content.contains("kickout")) {
                            //被踢
                            isReturn = true;
                            LogUtilBase.LogD(ClientChatXmppImpl.class.getSimpleName(), "this user is kickout");

                            //被踢 发消息
                            ObserverManager.getInstance().notifyAsync(
                                    ObserverConst.NOTIFY_CHAT_MESSAGE_LECTURE_FORBIDEN, 0, null);
                        } else if (content.equals("normal")) {
                            //消息发送成功
                            isReturn = true;

                            ServerReceiptExtension serverReceiptExtension = message.getExtension(ServerReceiptExtension.ELEMENT_NAME,
                                    ServerReceiptExtension.NAMESPACE);
                            ChatRoomMessage chatRoomMessage = MessageBuilder.buildRoomMessageFromServerReceipt(0, serverReceiptExtension, serverReceiptExtension.getMessageId());
                            LogUtilBase.LogD(TAG, "onReceiveReceiptRoom for server receipt:" + chatRoomMessage.getMessageId());
                            xmppListener.onReceiveReceiptRoom(chatRoomMessage);
                        }
                    } else if(type.equals(Constants.Chat.CHAT) || type.equals(Constants.Chat.ASK_DOCTOR)) {
                        //私聊消息回执
                        //医生私聊，不是好友关系
                        if (content.contains("stranger")) {
                            //不是好友关系
                            //暂时不处理
                            isReturn = true;
                            //Server_externsion toId = self, from=Server,so Ids have no value to use
                            ServerReceiptExtension serverReceiptExtension = message.getExtension(ServerReceiptExtension.ELEMENT_NAME,
                                    ServerReceiptExtension.NAMESPACE);
                            chatMessage = MessageBuilder.buildMessageFromServerReceipt(0, serverReceiptExtension, serverReceiptExtension.getMessageId());
                            LogUtilBase.LogD(TAG, "onReceiveReceipt for server receipt:" + chatMessage.getMessageId());
                            xmppListener.onReceiveReceipt(chatMessage);

                        } else if (content.equals("normal")) {
                            //消息发送成功
                            isReturn = true;
                            //Server_externsion toId = self, from=Server,so Ids have no value to use
                            ServerReceiptExtension serverReceiptExtension = message.getExtension(ServerReceiptExtension.ELEMENT_NAME,
                                    ServerReceiptExtension.NAMESPACE);
                            chatMessage = MessageBuilder.buildMessageFromServerReceipt(0, serverReceiptExtension, serverReceiptExtension.getMessageId());
                            LogUtilBase.LogD(TAG, "onReceiveReceipt for server receipt:" + chatMessage.getMessageId());
                            xmppListener.onReceiveReceipt(chatMessage);
                        }

                    }else if(type.equals(Constants.Chat.NOTICE))
                    {
                        LogUtilBase.LogD(TAG, "xmpp 发送通知成功");
                    }

                    if (isReturn)
                        return;
                }

                //接收到消息
                PacketExtension clientHuiZhi = message.getExtension(ServerReceiptExtension.ELEMENT_NAME,
                        ServerReceiptExtension.NAMESPACE_CLIENT);

                if(clientHuiZhi != null)
                {
                    return;
                }

                long sentTime = System.currentTimeMillis();

                //3. test for receive offline message
                //http://xmpp.org/extensions/xep-0203.html; http://xmpp.org/extensions/xep-0091.html
                PacketExtension delayExtension = message.getExtension("delay", "urn:xmpp:delay");
                boolean isOffline = false;
                if (delayExtension != null) {
                    isOffline = true;
                }

                PacketExtension receivedMessageExtendExtension = message.getExtension(
                        ChatRoomPacketExtension.ELEMENT_NAME_EXTEND, ChatRoomPacketExtension.NAMESPACE_EXTEND);

                if (receivedMessageExtendExtension != null) {
                   String groupID = ((DefaultPacketExtension) receivedMessageExtendExtension).getValue(
                           ChatRoomPacketExtension.SUB_ELEMENT_NAME_INFO_GROUP_ID);

                    if (!TextUtils.isEmpty(groupID)) {

                        //test online offline time new elementname
                        PacketExtension stampExtension = message.getExtension(
                                "sendtime-info", "jabber:lepu:sendtime");
                        if(stampExtension != null){
                            String time = ((DefaultPacketExtension) stampExtension).getValue(
                                    "sendtime");
                            if(!TextUtils.isEmpty(time)){
                                sentTime = UtilityBase.parseLong(time);
                                String dateString = DateUtilBase.stringFromDate(new Date(sentTime),DateUtilBase.DATE_ALL_ALL);
                                LogUtilBase.LogD(TAG, "process online message sent at dateString- " + dateString);
                            }
                            LogUtilBase.LogD(TAG, "process online message sent at sentTime- " + time);
                        }

                        String toId = message.getTo().split("@")[0];
                        String fromId = message.getFrom().split("@")[0];

                        ChatRoomMessage chatRoomMessage = MessageBuilder.buildChatRoomReceivedMessage(Constants.Chat.CHAT_MESSAGE_TYPE_TEXT, toId, fromId,
                                message.getPacketID(), message.getBody(), sentTime);

                        if(isOffline)
                        {
                            chatRoomMessage.setSendStatus(Constants.Chat.CHAT_SEND_STATUS_OFFLINE);
                        }

                        MediaPacketExtension mediaExtension = message.getExtension(
                                MediaPacketExtension.ELEMENT_NAME,
                                MediaPacketExtension.NAMESPACE);
                        if (mediaExtension != null) {
                            Media media = MessageBuilder.buildMedia(mediaExtension);
                            media.setChatType(Constants.Chat.GROUPCHAT);
                            chatRoomMessage.setMedia(media);
                            chatRoomMessage.setMessageType(media.getMessageType());
                        }
                        chatRoomMessage.setChatRoomID(groupID);
                        xmppListener.onReceiveGroupChatMessage(chatRoomMessage);

                        //收到消息 给服务器发送回执
                        if(!isOffline)
                        {
                            sendServerHuiZhiRoom(chatRoomMessage);
                        }

                        boolean atRoom = false;
                        ChatMainActivity instance = (ChatMainActivity) AppManager.getAppManager().getActivity(ChatMainActivity.class);
                        if(instance != null)
                        {
                            if(instance.mType == ChatConst.TYPE_ONLINE_CHAT_LECTURE){
                                atRoom = true;
                            }
                        }

                        //不在群聊里
                        if(!atRoom){

                            //at人的userid
                            PacketExtension receiveAtExtension = message.getExtension(
                                    "received-info", "jabber:lepu:received");
                            if(receiveAtExtension != null){
                                String value = ((DefaultPacketExtension) receiveAtExtension).getValue(
                                        "received");
                                if(!TextUtils.isEmpty(value)){
                                    String messageID = UserConfig.getConfigString(MyApplication.getInstance(),
                                            Const.CONFIG_APP_CHAT_ROOM_AT_RECEIVE_MESSAGE_ID, "");
                                    if(TextUtils.isEmpty(messageID) && value.contains(LoginUtil.getUserId())){
                                        UserConfig.setConfig(MyApplication.getInstance(),
                                                Const.CONFIG_APP_CHAT_ROOM_AT_RECEIVE_MESSAGE_ID, chatRoomMessage.getMessageId());
                                    }
                                }
                            }
                        }

                        LogUtilBase.LogD(TAG, "onReceiveReceipt for receive receipt:" + chatRoomMessage.getMessageId());
                    } else {

                        //test online offline time new elementname
                        if(isOffline){
                            PacketExtension stampExtension = message.getExtension(
                                    "message-sendtime", "urn:xmpp:timestamp");
                            if(stampExtension != null){
                                String time = ((DefaultPacketExtension) stampExtension).getValue(
                                        "sendtime");
                                if(!TextUtils.isEmpty(time)){
                                    sentTime = UtilityBase.parseLong(time);
                                    String dateString = DateUtilBase.stringFromDate(new Date(sentTime),DateUtilBase.DATE_ALL_ALL);
                                    LogUtilBase.LogD(TAG, "process online message sent at dateString- " + dateString);
                                }
                                LogUtilBase.LogD(TAG, "process online message sent at sentTime- " + time);
                            }
                        }

                        //私聊
                        long toId = Long.valueOf(message.getTo().split("@")[0]);
                        long fromId = Long.valueOf(message.getFrom().split("@")[0]);

                        // 判断是否来自在线咨询
                        String consult = ((DefaultPacketExtension) receivedMessageExtendExtension).getValue(
                                FromTypeExtension.SUB_ELEMENT_NAME_INFO_1);
                        if (!TextUtils.isEmpty(consult) && consult.equals(Constants.Chat.INFO_CONSULT)) {
                            chatMessage = MessageBuilder.buildReceivedMessage(
                                    Constants.Chat.CHAT_MESSAGE_TYPE_TEXT, toId, fromId,
                                    message.getPacketID(), message.getBody(),
                                    sentTime);

                            if(isOffline)
                            {
                                chatMessage.setSendStatus(Constants.Chat.CHAT_SEND_STATUS_OFFLINE);
                            }

                            MediaPacketExtension mediaExtension = message.getExtension(
                                    MediaPacketExtension.ELEMENT_NAME,
                                    MediaPacketExtension.NAMESPACE);
                            if (mediaExtension != null) {
                                Media media = MessageBuilder.buildMedia(mediaExtension);
                                media.setChatType(Constants.Chat.CHAT);
                                chatMessage.setMedia(media);
                                chatMessage.setMessageType(media.getMessageType());
                            }
                            xmppListener.onReceiveStaffMessage(chatMessage);

                            if(!isOffline)
                            {
                                sendServerHuiZhi(chatMessage);
                            }
                        } else if (!TextUtils.isEmpty(consult) && consult.equals(Constants.Chat.INFO_ASK_DOCTOR)){
                            // 及时聊天只有 文字
                            chatMessage = MessageBuilder.buildReceivedMessage(
                                    Constants.Chat.CHAT_MESSAGE_TYPE_TEXT, toId, fromId,
                                    message.getPacketID(), message.getBody(),
                                    sentTime);

                            if(isOffline)
                            {
                                chatMessage.setSendStatus(Constants.Chat.CHAT_SEND_STATUS_OFFLINE);
                            }

                            MediaPacketExtension mediaExtension = message.getExtension(
                                    MediaPacketExtension.ELEMENT_NAME,
                                    MediaPacketExtension.NAMESPACE);
                            if (mediaExtension != null) {
                                Media media = MessageBuilder.buildMedia(mediaExtension);
                                media.setChatType(Constants.Chat.CHAT);
                                chatMessage.setMedia(media);
                                chatMessage.setMessageType(media.getMessageType());
                            }
                            xmppListener.onReceiveMessage(chatMessage);

                            if(!isOffline)
                            {
                                sendServerHuiZhi(chatMessage);
                            }
                        }else if (!TextUtils.isEmpty(consult) && consult.equals(Constants.Chat.INFO_DoctorToUser)){
                            //通知
                            LogUtilBase.LogD(TAG,"接收到通知消息");
                            AppService appService = AppService.getInstance();
                            if(appService != null)
                            {
                                appService.requestCheckDoctorChange();
                            }
                        }
                    }
                    return;
                }
//=============================================================================================================================
            }
        };
        connection
                .addPacketListener(iqListener, new PacketTypeFilter(IQ.class));
        connection.addPacketListener(msgListener, new PacketTypeFilter(
                Message.class));
    }

    public void sendServerHuiZhi(ChatMessage chatMessage) {

        String jid = chatMessage.getToUserId()+"";
        Message message = new Message(jid, Message.Type.chat);
        DeliveryReceiptManager.addDeliveryReceiptRequest(message);

        //拼接message
        message.setPacketID(chatMessage.getMessageId());

        message.setFrom(MessageBuilder.getDomain(String.valueOf(chatMessage.getHostUserId())));
        message.setTo(Constants.Chat.CHAT_FROM_SERVER);

        ServerReceiptExtension serverReceiptExtension = new ServerReceiptExtension(ServerReceiptExtension.ELEMENT_NAME,
                ServerReceiptExtension.NAMESPACE_CLIENT);
        //医生端才接收通知
//        if(chatMessage.getFromUserId() == Constants.AskDoctorAddNotice)
//        {
//            serverReceiptExtension.setContent(Constants.Chat.NOTICE);
//        }
        serverReceiptExtension.setMessageId(chatMessage.getMessageId());
        message.addExtension(serverReceiptExtension);

        try {
            connection.sendPacket(message);
        } catch (SmackException.NotConnectedException e) {
            e.printStackTrace();
        }
    }

    public void sendServerHuiZhiRoom(ChatRoomMessage chatRoomMessage) {

        String jid = chatRoomMessage.getToUserId();
        Message message = new Message(jid, Message.Type.chat);
        DeliveryReceiptManager.addDeliveryReceiptRequest(message);

        //拼接message
        message.setPacketID(chatRoomMessage.getMessageId());

        message.setFrom(MessageBuilder.getDomain(String.valueOf(chatRoomMessage.getHostUserId())));
        message.setTo(Constants.Chat.CHAT_FROM_SERVER);

        ServerReceiptExtension serverReceiptExtension = new ServerReceiptExtension(ServerReceiptExtension.ELEMENT_NAME,
                ServerReceiptExtension.NAMESPACE_CLIENT);
        serverReceiptExtension.setMessageId(chatRoomMessage.getMessageId());
        message.addExtension(serverReceiptExtension);

        try {
            connection.sendPacket(message);
        } catch (SmackException.NotConnectedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void sendServerTimeIQ() {
        Packet packet = new ServerTimeIQ(
                "<query xmlns='http://kanebay.com/protocol/server#time'></query>");
        try {
            connection.sendPacket(packet);
        } catch (Exception e) {
        }
    }

    @Override
    public void sendMessageIQ(long fromId, long toId, String packetId) {
        try {
            MessageStateIQ packet = new MessageStateIQ(
                    "<query xmlns='http://kanebay.com/protocol/offlinemessage#exist'>"
                            + "<message from='" + fromId + "' to='" + toId
                            + "' id='" + packetId + "' /></query>");
            if (isConnectionClosed()) {
                return;
            }

            connection.sendPacket(packet);

        } catch (Exception e) {
        }
    }

    private void notifyChatStateChange(int what, Bundle data) {
        android.os.Message msg = new android.os.Message();
        if (data != null) {
            msg.setData(data);
        }
        msg.what = what;
        // ChatManager.getInstance().onMessage(msg);
    }

    @Override
    public void setConnectionClosed(boolean value) {
        connectionClosed = value;
    }

    @Override
    public boolean isConnectionClosed() {
        return connectionClosed;
    }

    @Override
    public boolean isConnectionValid() {
        if ((connection == null) || isConnectionClosed()) {
            return false;
        }
        return true;
    }

    @Override
    public XMPPConnection getConnection() {
        return connection;
    }

    @Override
    public void setXmppListener(XmppListener callback) {
        this.xmppListener = callback;
    }

    @Override
    public void startConnectTimer()
    {
        if (mConnectTimer == null) {
            LogUtilBase.LogD(TAG,"异常连接断开，开启自定义重连");
            mConnectTimer = new Timer();
            mConnectTimer.schedule(new TimerTask() {

                @Override
                public void run() {
                    LogUtilBase.LogD(TAG,"自定义重连");
                    LoginUtil.loginOpenFire();
                }
            }, 0, 15*1000);
        }
    }

    @Override
    public void stopConnectTimer()
    {
        if (mConnectTimer != null) {
            LogUtilBase.LogD(TAG,"自定义重连 关闭");

            mConnectTimer.cancel();
            mConnectTimer.purge();
            mConnectTimer = null;
        }
    }

}